package ru.linnenson.darshana.infrastructure.rest;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import ru.linnenson.darshana.application.services.MathTasksStoreService;
import ru.linnenson.darshana.application.services.TasksCreator;
import ru.linnenson.darshana.infrastructure.persistence.models.MathTaskStore;
import ru.linnenson.darshana.infrastructure.rest.dto.CreateMathTaskDto;
import ru.linnenson.darshana.infrastructure.rest.dto.EntityIdDto;
import ru.linnenson.darshana.infrastructure.rest.dto.MathTaskResponse;
import ru.linnenson.darshana.infrastructure.rest.dto.MathTasksCriteria;
import ru.linnenson.darshana.infrastructure.rest.dto.ParsedPhotoResponse;
import ru.linnenson.darshana.infrastructure.rest.dto.PhotoIdDto;
import ru.linnenson.darshana.infrastructure.rest.mappers.MathTasksMapper;
import ru.linnenson.darshana.infrastructure.services.ParsedPhotoDto;
import java.io.IOException;

@Slf4j
@RestController
@RequestMapping("/api/math-tasks")
@RequiredArgsConstructor
public class MathTasksResource {

  private final TasksCreator tasksCreator;
  private final MathTasksMapper mathTasksMapper;
  private final MathTasksStoreService mathTasksStoreService;

  @GetMapping
  public ResponseEntity<Page<MathTaskResponse>> search(final MathTasksCriteria criteria,
                                                       @PageableDefault(sort = "id") final Pageable pageable) {

    log.debug("find math task by criteria {} pageable {}", criteria, pageable);

    final Page<MathTaskStore> tasks = mathTasksStoreService.search(criteria, pageable);

    return ResponseEntity.ok(tasks.map(mathTasksMapper::toDto));
  }

  @PostMapping
  public ResponseEntity<EntityIdDto> create(@RequestBody final CreateMathTaskDto dto) {

    log.info("Request to create new math task: {}", dto);

    final Integer id = tasksCreator.createMath(dto.getSource(), dto.getTheme(), dto.getNumberInKim(), dto.getTags());

    log.info("Request to create new math task finished with id: {}", id);

    return ResponseEntity.ok(new EntityIdDto(id));
  }

  @PostMapping("/{taskId}/photos")
  public ResponseEntity<ParsedPhotoResponse> addPhoto(@PathVariable Integer taskId,
                                                      @RequestParam("file") MultipartFile file) throws IOException {

    log.info("Request to add photo to task {}", taskId);

    final ParsedPhotoDto photo = mathTasksStoreService.addPhoto(taskId, file.getBytes());

    log.info("Request to add photo to task {} finished with result [{}]", taskId, photo);

    return ResponseEntity.ok(new ParsedPhotoResponse(photo.id(), photo.text()));
  }

  @PostMapping("/{taskId}/solution-photos")
  public ResponseEntity<PhotoIdDto> addSolutionPhoto(@PathVariable Integer taskId,
                                                     @RequestParam("file") MultipartFile file) throws IOException {

    final String photoId = mathTasksStoreService.addSolutionPhoto(taskId, file.getBytes());

    return ResponseEntity.ok(new PhotoIdDto(photoId));
  }

  @DeleteMapping("/{taskId}/photos/{photoId}")
  public ResponseEntity<?> deletePhoto(@PathVariable Integer taskId, @PathVariable String photoId) {

    mathTasksStoreService.deletePhoto(taskId, photoId);

    return ResponseEntity.noContent().build();
  }

  @DeleteMapping("/{taskId}/solution-photos/{photoId}")
  public ResponseEntity<?> deleteSolutionPhoto(@PathVariable Integer taskId, @PathVariable String photoId) {

    mathTasksStoreService.deleteSolutionPhoto(taskId, photoId);

    return ResponseEntity.noContent().build();
  }
}
